<?php

namespace control;

/*
*会计科目类
*/

class subjectClass extends adIndexClass
{
    private const page  = 'subject';
    private const table = 'subject';
    private const title = '科目';
    public static array $typeOption = ['asset' => '资产', 'debt' => '负债', 'interests' => '权益', 'cost' => '成本', 'loss' => '损益'];//2013小企业会计准则
    public static array $assitOption = ['客户', '供应商', '员工', '部门', '项目', '存货', '现金流'];
    private static array $codeRule = [4, 3, 2];//编码规则
    private static array $codePre = ['资产类' => 1, '负债类' => 2, '权益类' => 3, '成本类' => 4, '损益类' => 5];//2013小企业会计准则
    private int $level = 4;//科目最多新建层级

    /**
     * 根据企业会计准则返回对应的科目页卡
     * @return array
     */
    public static function enterpriseSubjectTab(): array
    {
        if (companyClass::returnRule(1) == 'enterpriseRule') {
            return ['asset' => '资产', 'debt' => '负债', 'common' => '共同', 'interests' => '权益', 'cost' => '成本', 'loss' => '损益'];
        } elseif (companyClass::returnRule(1) == 'smallEnterpriseRule') {
            return self::$typeOption;
        }
        return [];
    }

    /**
     * 根据企业会计准则返回对应科目前缀
     * @return array
     */
    public static function enterpriseCodePre(): array
    {
        if (companyClass::returnRule(1) == 'enterpriseRule') {
            return ['资产类' => 1, '负债类' => 2, '共同类' => 3, '权益类' => 4, '成本类' => 5, '损益类' => 6];
        } elseif (companyClass::returnRule(1) == 'smallEnterpriseRule') {
            return self::$codePre;
        }
        return [];
    }

    /**
     * 查询表单
     *
     * @param string $workFlow
     * @return string
     */
    public function homeForm($workFlow = ''): string
    {
        //生成查询表单
        $html = '';
        return $this->searchExecute([
                'html'        => $html,
                'type'        => 'menu',
                'otherButton' => 'no',
                'option'      => '{fixed:true}',
                'isSearch'    => false,
            ]) . <<<eof
<style>
.pageDiv{overflow: auto}
</style>
eof;
//        return $this->search($html, 'menu', 'no');
    }

    /*列表-查询条件*/
    public function home()
    {
        //生成查询表单
        $data             = [
            "id"   => "all",
            "menu" => self::enterpriseSubjectTab()
        ];
        $data['html']     = $this->homeForm();
        $data['pageType'] = 'list';
        return $this->tab($data);
    }

    /*客户列表-查询结果*/
    public function homeSearch()
    {
        $subjectType = '资产类';
        //like查询数组
        $like = array();
        //全等查询数组
        $equal        = array(
            'coid'  => self::$coid,
            'type'  => $subjectType,
            'level' => 1
        );
        $generalWhere = '';
        $isShowStop   = companyClass::getSetting('isShowStopSubject');
        if ($isShowStop == 2) {
            $generalWhere .= " and state = '启用'";
        }
        //获取查询结果
        $where = search(array("like" => $like, "=" => $equal)) . $generalWhere;
        $page  = $this->page(array("table" => self::table, 'pageNum' => 1000, "where" => $where, "order" => "code asc"));
        static::rSet(self::$stid . self::page . 'AssetSql', $page['fullSql']);
        //获取表头
        $checkAll = $this->checkAll("listForm", "listId");
        $tr[]     = array($checkAll, "科目编码", "科目名称", "类别", "余额方向", "数量核算", "辅助核算", "外币核算", '状态');
        //获取记录
        foreach ($page['array'] as $array) {
            $res = $this->loopSubject($array, $subjectType, $generalWhere);
            $tr  = array_merge($tr, $res);
        }
        //控件
        $button = $this->button($subjectType, 'listForm');
        //返回
        $json['html'] = $button . "<form name='listForm'>" . space . $this->tableMany(array("tr" => $tr, "displayFields" => false, "showSort" => true)) . "</form>" . clear;
        return json_encode($json, 320);
    }

    private function loopSubject($array, $subjectType, $generalWhere = ''): array
    {
        $tr          = [];
        $isExitChild = false;
        if (static::total(array('table' => self::table, 'where' => "pid = '$array[id]'")) > 0) {
            $isExitChild = true;
        }
        //列表控件
        $dominate = array(
            "box"     => array("name" => "listId", "value" => $array['id']),
            'edit'    => array("title" => "编辑", "click" => "layer('" . self::page . "','edit',{id:'" . $array['id'] . "'})"),
            'add_one' => $array['level'] < $this->level ? array("title" => "添加下级", "click" => "layer('" . self::page . "','edit',{pid:'" . $array['id'] . "',type:'{$subjectType}'})") : [],
            'add'     => $array['level'] < $this->level ? array("title" => "批量添加下级", "click" => "layer('" . self::page . "','batchAdd',{pid:'" . $array['id'] . "',type:'{$subjectType}'})") : [],
        );
        $empty    = '';
        if ($array['level'] > 1) {
            for ($i = 1; $i < $array['level']; $i++) {
                $empty .= "&emsp;";
            }
        }
        $currency = query('currency', "id = '$array[currencyAccountIds]'");
        $temp     = array($this->dominate($dominate), $empty . $array['code'], $empty . $array['name'], $array['type'], $array['direction'], $array['numAccountText'], $array['assistAccountIds'], $currency['code'], $array['state']);
        $tr[]     = $temp;
        //判断是否有下级分类
        if ($isExitChild) {
            $levelTwoRes = find(array('table' => self::table, 'where' => "pid = '$array[id]' $generalWhere order by code"));
            foreach ($levelTwoRes['array'] as $val) {
                $res = $this->loopSubject($val, $subjectType, $generalWhere);
                $tr  = array_merge($tr, $res);
            }
        }
        return $tr;
    }

    /**
     * 操作按钮
     * @param $subjectType
     * @param $formName
     * @return string
     */
    private function button($subjectType, $formName): string
    {
        $button = "";
        if ($this->power(self::page, "edit")) {
            $button .= "<span onclick=\"layer('" . self::page . "','codeSetting',{})\" class='spanButton'>编码设置</span>\n";
            if (companyClass::returnRule(1) == 'enterpriseRule') {
                $button .= "<span onclick=\"layer('" . self::page . "','add',{type:'{$subjectType}'})\" class='spanButton'>新增科目</span>\n";
            }
            $button .= "<span onclick=\"layer('{$this->get('cla')}','stateSwitch',{type:'启用',formName:'$formName'})\" class='spanButton'>启用</span>\n";
            $button .= "<span onclick=\"layer('{$this->get('cla')}','stateSwitch',{type:'停用',formName:'$formName'})\" class='spanButton'>停用</span>\n";
        }
        if ($this->power(self::page, "del")) {
            $button .= "<span class='spanButton' onclick=\"layer('{$this->get('cla')}', 'operate', {'act': 'del'})\">删除</span>\n";
        }

        if ($this->power(self::page, 'import')) {
            $button .= "<span class='spanButton' onclick=\"layer('importTemplate','importFrame',{cla:'" . self::page . "',importFun:'import'})\">导入</span>";
        }
        if ($this->power(self::page, "export")) {
            $button .= "  <a href='" . root . "control/adIndex.html?cla=" . $this->get('cla') . "&fun=exportData&type=" . $subjectType . "'><span class='spanButton'>导出</span></a>\n";
        }
        $checked = companyClass::getSetting('isShowStopSubject') == 2 ? 'checked' : '';
        $button  .= <<<eof
<div>
  <input type="checkbox" id="text-switch" class="text-switch" $checked />
  <label for="text-switch">显示停用科目</label>
</div>
<script>
$(function() {
   textSwitch($(".text-switch"))
})
// 获取当前开关
$(".text-switch").on("change", function () {
  textSwitch($(this));
  setTimeout(function() {
     $.post(root+'control/adIndex.html?cla=subject&fun=showStopSubjectEdit',{},function(res) {
      if (res.warn === 2){
          location.reload();
      }else{
          warn(res.warn,'error')
      }
    },'json') 
  },500)

});
function textSwitch(_this){
   let label = $(".text-switch + label");
   if (_this.is(":checked")) {
        //隐藏停用科目
        label.html('隐藏停用科目');
        label.css({'padding-right':'30px','padding-left':'12px'})
    } else {
        label.html('显示停用科目');
        label.css({'padding-right':'12px','padding-left':'30px'})
    }
   
}    
</script>
eof;

        return "<div class='flex-box m-t-10'>" . $button . "</div>";
    }

    public function codeSetting()
    {
        $company    = query('company', "coid = '" . self::$coid . "'");
        $codeLength = explode('-', $company['codeLength']);
        $example    = [];
        foreach ($codeLength as $index => $num) {
            if ($index == 0) {
                $example[] = +pow(10, $num - 1) + 1;
            } else {
                $example[] = sprintf("%0{$num}d", 1);
            }

        }
        $html = $this->layerEdit(array("table" => array(
            array(
                '编码长度：' => "<span style='margin-right: 20px'>$codeLength[0]</span>-" . text(['name' => 'codeLength[]', 'class' => 'width50 center', 'value' => $codeLength[1]]) . '-' . text(['name' => 'codeLength[]', 'class' => 'width50 center', 'value' => $codeLength[2]]) . '-' . text(['name' => 'codeLength[]', 'class' => 'width50 center', 'value' => $codeLength[3]])
            ),
            array(
                '示例：' => "<span>" . implode('-', $example) . "</span>"
            )
        )));
        //返回
        return $this->layer(array("title" => "编码设置", "height" => 200, "html" => $html));
    }

    public function codeSettingEdit()
    {
        $codeLength = $this->post('codeLength');
        if (!$this->power(self::page, "edit")) {
            $json['warn'] = "你没有" . self::title . "的编辑权限";
        } elseif (self::is_null_array($codeLength)) {
            $json['warn'] = "请填写编码长度";
        } else {
            $company      = query('company', "coid = '" . self::$coid . "'");
            $length       = array_merge([4], $codeLength);
            $field        = [
                'codeLength' => implode('-', $length),
            ];
            $json['warn'] = update(array('table' => 'company', 'field' => $field, 'where' => " coid ='" . self::$coid . "'"));
            if (in_array($json['warn'], ["新增成功", "更新成功"])) {
                //添加日志
                $text = $this->control['name'] . "更新了账套【{$company['name']}】的编码长度";
                $this->logText(["type" => self::page, "text" => $text]);
                //返回
                $_SESSION['warn'] = $json['warn'];
                $json['warn']     = 2;
            }
        }
        //返回
        return json_encode($json, 320);
    }

    /**
     * 启用/停用
     */
    public function stateSwitch(): bool|string
    {
        $type = $this->post('type');
        //生成表单
        $html = $this->layerEdit(array("table" => array(
            array(
                "提示：" => "是否修改所选数据状态为：" . $type,
            ),
        ), 'hidden'                            => hidden(array('name' => 'type', 'value' => $type))));
        //返回
        return $this->layer(array("title" => "状态切换", "height" => 165, "html" => $html, 'formTwo' => $this->post('formName')));
    }

    /**
     * 启用/停用
     */
    public function stateSwitchEdit(): bool|string
    {
        $idArr = $this->post('id') ? [$this->post('id')] : $this->post('listId');
        $state = $this->post('type');
        if (!$this->power(self::page, "edit")) {
            $json['warn'] = "你没有" . self::title . "的编辑权限";
        } elseif (empty($idArr) || !is_array($idArr)) {
            $json['warn'] = "请选择数据";
        } elseif (!in_array($state, ['启用', '停用'])) {
            $json['warn'] = "类型错误";
        } else {
            $field        = [
                'state' => $state,
            ];
            $json['warn'] = update(array('table' => self::table, 'field' => $field, 'where' => " id in ('" . implode("','", $idArr) . "')"));
            if (in_array($json['warn'], ["新增成功", "更新成功"])) {
                //添加日志
                $type = mb_substr($json['warn'], 0, 2, 'utf-8');
                $text = $this->control['name'] . $type . "了" . self::title . "的状态为【{$state}】， id：【" . implode(",", $idArr) . '】';
                $this->logText(["type" => self::page, "text" => $text]);
                //返回
                $_SESSION['warn'] = $json['warn'];
                $json['warn']     = 2;
            }
        }
        //返回
        return json_encode($json, 320);
    }

    public function loss()
    {
        $json['html'] = $this->homeForm('损益');
        return json_encode($json, 320);
    }

    public function lossSearch(): bool|string
    {
        $subjectType = '损益类';
        //like查询数组
        $like = array();
        //全等查询数组
        $equal        = array(
            'coid'  => self::$coid,
            'type'  => $subjectType,
            'level' => 1,
        );
        $generalWhere = '';
        $isShowStop   = companyClass::getSetting('isShowStopSubject');
        if ($isShowStop == 2) {
            $generalWhere .= " and state = '启用'";
        }
        //获取查询结果
        $where = search(array("like" => $like, "=" => $equal)) . $generalWhere;
        $page  = $this->page(array("table" => self::table, 'pageNum' => 1000, "where" => $where, "order" => "code asc"));
        //获取表头
        $checkAll = $this->checkAll("lossForm", "listId");
        $tr[]     = array($checkAll, "科目编码", "科目名称", "类别", "数量核算", "辅助核算", "外币核算", "余额方向", '状态');
        static::rSet(self::$stid . self::page . 'lossSql', $page['fullSql']);
        //获取记录
        foreach ($page['array'] as $array) {
            $res = $this->loopSubject($array, $subjectType, $generalWhere);
            $tr  = array_merge($tr, $res);
        }
        //控件
        $button = $this->button($subjectType, 'lossForm');
        //返回
        $json['html'] = $button . "<form name='lossForm'>" . space . $this->tableMany(array("tr" => $tr, "displayFields" => false, "showSort" => true)) . "</form>" . clear;
        return json_encode($json, 320);
    }

    public function cost()
    {
        $json['html'] = $this->homeForm('成本');
        return json_encode($json, 320);
    }

    public function costSearch()
    {
        $subjectType = '成本类';
        //like查询数组
        $like = array();
        //全等查询数组
        $equal        = array(
            'coid'  => self::$coid,
            'type'  => $subjectType,
            'level' => 1,
        );
        $generalWhere = '';
        $isShowStop   = companyClass::getSetting('isShowStopSubject');
        if ($isShowStop == 2) {
            $generalWhere .= " and state = '启用'";
        }
        //获取查询结果
        $where = search(array("like" => $like, "=" => $equal)) . $generalWhere;
        $page  = $this->page(array("table" => self::table, 'pageNum' => 1000, "where" => $where, "order" => "code asc"));
        static::rSet(self::$stid . self::page . 'costSql', $page['fullSql']);
        //获取表头
        $checkAll = $this->checkAll("costForm", "listId");
        $tr[]     = array($checkAll, "科目编码", "科目名称", "类别", "数量核算", "辅助核算", "外币核算", "余额方向", '状态');
        //获取记录
        foreach ($page['array'] as $array) {
            $res = $this->loopSubject($array, $subjectType, $generalWhere);
            $tr  = array_merge($tr, $res);
        }
        //控件
        $button = $this->button($subjectType, 'costForm');
        //返回
        $json['html'] = $button . "<form name='costForm'>" . space . $this->tableMany(array("tr" => $tr, "displayFields" => false, "showSort" => true)) . "</form>" . clear;
        return json_encode($json, 320);
    }

    public function interests()
    {
        $json['html'] = $this->homeForm('权益');
        return json_encode($json, 320);
    }

    public function interestsSearch()
    {
        $subjectType = '权益类';
        //like查询数组
        $like = array(
            "name" => $this->post('name'),
            "code" => $this->post('code'),
        );
        //全等查询数组
        $equal        = array(
            'coid'  => self::$coid,
            'type'  => $subjectType,
            'level' => 1,
        );
        $generalWhere = '';
        $isShowStop   = companyClass::getSetting('isShowStopSubject');
        if ($isShowStop == 2) {
            $generalWhere .= " and state = '启用'";
        }
        //获取查询结果
        $where = search(array("like" => $like, "=" => $equal)) . $generalWhere;
        $page  = $this->page(array("table" => self::table, 'pageNum' => 1000, "where" => $where, "order" => "code asc"));
        static::rSet(self::$stid . self::page . 'interestsSql', $page['fullSql']);
        //获取表头
        $checkAll = $this->checkAll("interestsForm", "listId");
        $tr[]     = array($checkAll, "科目编码", "科目名称", "类别", "数量核算", "辅助核算", "外币核算", "余额方向", '状态');
        //获取记录
        foreach ($page['array'] as $array) {
            $res = $this->loopSubject($array, $subjectType, $generalWhere);
            $tr  = array_merge($tr, $res);
        }
        //控件
        $button = $this->button($subjectType, 'interestsForm');
        //返回
        $json['html'] = $button . "<form name='interestsForm'>" . space . $this->tableMany(array("tr" => $tr, "displayFields" => false, "showSort" => true)) . "</form>" . clear;
        return json_encode($json, 320);
    }

    public function common()
    {
        $json['html'] = $this->homeForm('共同');
        return json_encode($json, 320);
    }

    public function commonSearch()
    {
        $subjectType = '共同类';
        //like查询数组
        $like = array();
        //全等查询数组
        $equal        = array(
            'coid'  => self::$coid,
            'type'  => $subjectType,
            'level' => 1,
        );
        $generalWhere = '';
        $isShowStop   = companyClass::getSetting('isShowStopSubject');
        if ($isShowStop == 2) {
            $generalWhere .= " and state = '启用'";
        }
        //获取查询结果
        $where = search(array("like" => $like, "=" => $equal)) . $generalWhere;
        $page  = $this->page(array("table" => self::table, 'pageNum' => 1000, "where" => $where, "order" => "code asc"));
        static::rSet(self::$stid . self::page . 'commonSql', $page['fullSql']);
        //获取表头
        $checkAll = $this->checkAll("commonForm", "listId");
        $tr[]     = array($checkAll, "科目编码", "科目名称", "类别", "数量核算", "辅助核算", "外币核算", "余额方向", '状态');
        //获取记录
        foreach ($page['array'] as $array) {
            $res = $this->loopSubject($array, $subjectType, $generalWhere);
            $tr  = array_merge($tr, $res);
        }
        //控件
        $button = $this->button($subjectType, 'commonForm');
        //返回
        $json['html'] = $button . "<form name='commonForm'>" . space . $this->tableMany(array("tr" => $tr, "displayFields" => false, "showSort" => true)) . "</form>" . clear;
        return json_encode($json, 320);
    }


    public function debt()
    {
        $json['html'] = $this->homeForm('负债');
        return json_encode($json, 320);
    }

    public function debtSearch()
    {
        $subjectType = '负债类';
        //like查询数组
        $like = array(
            "name" => $this->post('name'),
            "code" => $this->post('code'),
        );
        //全等查询数组
        $equal        = array(
            'coid'  => self::$coid,
            'type'  => $subjectType,
            'level' => 1,
        );
        $generalWhere = '';
        $isShowStop   = companyClass::getSetting('isShowStopSubject');
        if ($isShowStop == 2) {
            $generalWhere .= " and state = '启用'";
        }
        //获取查询结果
        $where = search(array("like" => $like, "=" => $equal)) . $generalWhere;
        $page  = $this->page(array("table" => self::table, 'pageNum' => 1000, "where" => $where, "order" => "code asc"));
        static::rSet(self::$stid . self::page . 'debtSql', $page['fullSql']);
        //获取表头
        $checkAll = $this->checkAll("debtForm", "listId");
        $tr[]     = array($checkAll, "科目编码", "科目名称", "类别", "数量核算", "辅助核算", "外币核算", "余额方向", '状态');
        //获取记录
        foreach ($page['array'] as $array) {
            $res = $this->loopSubject($array, $subjectType, $generalWhere);
            $tr  = array_merge($tr, $res);
        }
        //控件
        $button = $this->button($subjectType, 'debtForm');
        //返回
        $json['html'] = $button . "<form name='debtForm'>" . space . $this->tableMany(array("tr" => $tr, "displayFields" => false, "showSort" => true)) . "</form>" . clear;
        return json_encode($json, 320);
    }


    /**
     * 获取编码长度
     * @return string[]
     */
    public function getCodeLength()
    {
        $company = query("company", "coid = '" . self::$coid . "'");
        return explode('-', $company['codeLength']);
    }

    /**
     * 科目编码
     */
    public function subjectCode($type, $pid, $num = 1)
    {
        self::$codeRule = $this->getCodeLength();
        $preFix         = self::enterpriseCodePre()[$type];
        $parent         = query(self::table, "id = '$pid'");
        if (empty($parent['id'])) {
            //一级
            $last    = query(self::table, "coid = '" . self::$coid . "' and type = '$type' and level = 1 order by code desc");
            $orderNo = $last['id'] ? $last['code'] + $num : $preFix . sprintf("%0" . (self::$codeRule[0] - 1) . "d", $num);
        } else {
            $level = $parent['level'] + 1;
            $last  = query(self::table, "coid = '" . self::$coid . "' and type = '$type' and level = $level and pid = '$pid' order by code desc");
            if ($last['id']) {
                $orderNo = $last['code'] + $num;
            } else {
                $orderNo = $parent['code'];
                foreach (self::$codeRule as $index => $val) {
                    if ($index + 1 == $level) {
                        $orderNo .= sprintf("%0" . (self::$codeRule[$index]) . "d", $num);
                        break;
                    }
                }
            }
        }
        return $orderNo;
    }

    /**
     * 批量添加下级科目
     * @return false|string
     */
    public function batchAdd()
    {
        $pid    = $this->post('pid');
        $parent = query(self::table, "id = '$pid'");
        $html   = $this->layerEdit([
                "table"  => [
                    [
                        '提示：' => "一行视为一个科目，多个科目换行设置"
                    ],
                    [
                        '上级科目：' => $parent['code'] . ' ' . $parent['name']
                    ],
                    [
                        textarea([
                            'name'  => 'subjectName',
                            'class' => 'textarea-normal',
                            'other' => "oninput='computeNum(this)'"
                        ])
                    ],
                    [
                        "科目数量" => "<span id='subjectNum'>0</span>个"
                    ]
                ],
                'hidden' => hidden(array('name' => 'pid', 'value' => $this->post('pid'))) . hidden(array('name' => 'type', 'value' => $this->post('type'))) . $this->js(),
            ]) . $this->layerJs();//
        //返回
        return $this->layer(array(
            "title"  => "批量添加下级科目",
            "height" => 400,
            "width"  => 800,
            "html"   => $html,
        ));
    }

    private function layerJs()
    {
        return <<<eof
<script>
//计算行数
function computeNum(e){
    var text = $(e).val(); // 获取textarea的值
    var lineBreaks = 0;
    if (text){
        lineBreaks= (text.match(/\\n/g) || []).length + 1;
    }
    $("#subjectNum").html(lineBreaks)
}
</script>
eof;
    }

    /**
     * 批量添加下级科目
     * @return false|string
     */
    public function batchAddEdit()
    {
        $pid      = $this->post('pid');
        $textarea = $this->post('subjectName');
        $lines    = array_unique(array_filter(explode("\n", $textarea)));
        //判断
        if (!$this->power(self::page, "edit")) {
            $json['warn'] = "你没有编辑" . self::title . "的权限";
        } elseif (empty($pid)) {
            $json['warn'] = '未找到上级科目';
        } elseif (self::is_null_array($lines)) {
            $json['warn'] = '请填写科目名称';
        } else {
            $parent = query(self::table, "id = '$pid'");
            $list   = $parent['list'];
            $level  = $parent['level'] + 1;
            if ($level > $this->level) {
                $json['warn'] = '最多新建' . $this->level . '层层级';
                goto resp;
            }
            $temp    = query(self::table, "coid = '" . self::$coid . "' and level = '$level' order by list desc");
            $log     = '';
            $success = 0;
            foreach ($lines as $index => $name) {
                $code      = $this->subjectCode($parent['type'], $parent['id']);
                $selfIndex = $temp['selfIndex'] ? ($temp['selfIndex'] + ($index + 1)) : 1;
                $field     = [
                    'id'                 => suiji(),
                    'coid'               => self::$coid,
                    'list'               => $list,
                    'selfIndex'          => $selfIndex,
                    'level'              => $level,
                    'pinyin'             => PYClass::encode($name),
                    'type'               => $parent['type'],
                    'code'               => $code,
                    'name'               => $name,
                    'direction'          => $parent['direction'],
                    'pid'                => $parent['id'],
                    'state'              => $parent['state'],
                    'numAccount'         => '否',
                    'assistAccount'      => '否',
                    'currencyAccount'    => '否',
                    'numAccountText'     => '',
                    'assistAccountIds'   => '',
                    'currencyAccountIds' => '',
                ];
                $warn      = self::insert([
                    'table' => self::table,
                    'field' => $field
                ]);
                if ($warn == '新增成功') {
                    $success++;
                    $log .= "科目【{$field['name']}】-【{$field['code']}】批量" . $warn . "\n";
                } else {
                    $log .= "科目【{$field['name']}】-【{$field['code']}】批量新增失败：" . $warn . "\n";
                }
            }
            if ($success > 0) {
                if ((static::total(array('table' => 'voucher_detail', 'where' => "subjectId = '$parent[id]'")) > 0 ||
                    static::total(array('table' => 'business_voucher_template_detail', 'where' => "subjectId = '$parent[id]'")) > 0 ||
                    static::total(array('table' => 'business_voucher_subject', 'where' => "subjectId = '$parent[id]'")) > 0 ||
                    static::total(array('table' => 'material', 'where' => "subjectId = '$parent[id]'")) > 0
                )) {
                    //如果父级有凭证，则新增一级相同名称的子级科目
                    $code  = $this->subjectCode($parent['type'], $parent['id']);
                    $suiji = suiji();
                    static::insert(array(
                        'table' => self::table,
                        'field' => [
                            'id'                 => $suiji,
                            'coid'               => self::$coid,
                            'list'               => $list,
                            'selfIndex'          => $temp['selfIndex'] ? ($temp['selfIndex'] + (count($lines) + 1)) : 1,
                            'level'              => $level,
                            'type'               => $parent['type'],
                            'code'               => $code,
                            'name'               => $parent['name'],
                            'pinyin'             => $parent['pinyin'],
                            'direction'          => $parent['direction'],
                            'pid'                => $parent['id'],
                            'initMoney'          => $parent['initMoney'],
                            'borrowMoney'        => $parent['borrowMoney'],
                            'loanMoney'          => $parent['loanMoney'],
                            'subjectSign'        => $parent['subjectSign'],
                            'state'              => $parent['state'],
                            'numAccount'         => $parent['numAccount'],
                            'assistAccount'      => $parent['assistAccount'],
                            'currencyAccount'    => $parent['currencyAccount'],
                            'numAccountText'     => $parent['numAccountText'],
                            'assistAccountIds'   => $parent['assistAccountIds'],
                            'currencyAccountIds' => $parent['currencyAccountIds'],
                        ]
                    ));
                    //凭证替换父级科目
                    $this->replaceSubjectId($parent['id'], $suiji, $code);
                }
                $text = $this->control['name'] . "批量新增科目如下\n" . $log;
                $this->logText(["type" => self::page, "text" => $text]);
            }
            //返回
            $_SESSION['warn'] = "成功新增了{$success}个科目";
            $json['warn']     = 2;
        }
        resp:
        return json_encode($json, 320);
    }


    /**
     * 新增一级科目
     * @return string
     */
    public function add(): string
    {
        array_pop(self::$assitOption);
        self::$assitOption = array_merge(self::$assitOption, ['现金流']);
        $direction         = '借';
        $disabled          = '';
        $currencyOption    = [];
        $currencyAll       = find(['table' => 'currency', 'where' => "coid = '" . self::$coid . "' order by time"]);
        foreach ($currencyAll['array'] as $array) {
            $currencyOption[$array['id']] = $array['code'] . '(' . $array['name'] . ')';
        }
        $class   = [
            'hide',
            'hide',
        ];
        $checked = [
            '',
            '',
        ];
        $html    = $this->layerEdit([
            "table"  => [
                [
                    must . "科目编码：" => text(["name" => "code"]),
                ],
                [
                    must . "科目名称：" => text(["name" => "name"]),
                ],
                [
                    must . "类别：" => radio(['name'=>'type','value'=>array_keys(self::enterpriseCodePre()),'checked'=>$this->post('type')]),
                ],
                [
                    must . '余额方向：' => radio(array('name' => 'direction', 'value' => ['借', '贷'], 'checked' => $direction))
                ],
                [
                    must . '科目状态：' => radio(array('name' => 'state', 'value' => ['启用', '停用'], 'checked' => '启用'))
                ],
                [
                    '外币核算：' => select(array('name' => 'currencyAccountIds', 'option' => $currencyOption, 'title' => '请选择外币符号'))
                ],
                [
                    "<label class='checkbox'><input name='numAccount' $checked[0]  onclick=\"chooseBox(this,'numAccount')\" type='checkbox' value='是'><span></span>&nbsp;数量核算：</label>" => "<span id='numAccount' class='{$class[0]}'>计量单位&nbsp;" . text(array('name' => 'numAccountText', 'class' => 'width100')) . "</span>"
                ],
                [
                    "<label class='checkbox'><input  name='assistAccount' $checked[1]  onclick=\"chooseBox(this,'assistAccount')\" type='checkbox' value='是'><span></span>&nbsp;辅助核算：</label>" => "<span id='assistAccount' class='{$class[1]}'>" . checkbox(array('name' => 'assistAccountIds', 'other' => $disabled, 'value' => self::$assitOption, 'checked' => [])) . "</span>"
                ],
            ],
            'hidden' => $this->js(),
        ]);//

        //返回
        return $this->layer(array(
            "title"  => "编辑",
            "height" => 600,
            "width"  => 800,
            "html"   => $html,
        ));
    }

    public function addEdit()
    {
        $id    = self::getId();
        $field = [
            'type'               => $this->post('type'),
            'code'               => $this->post('code'),
            'name'               => $this->post('name'),
            'direction'          => $this->post('direction'),
            'pid'                => 0,
            'state'              => '启用',
            'numAccount'         => $this->post('numAccount') ?: '否',
            'assistAccount'      => $this->post('assistAccount') ?: '否',
            'currencyAccount'    => $this->post('currencyAccountIds') ? '是' : '否',
            'numAccountText'     => $this->post('numAccount') == '是' ? $this->post('numAccountText') : '',
            'assistAccountIds'   => $this->post('assistAccount') == '是' ? implode(',', $this->post('assistAccountIds') ?: []) : '',
            'currencyAccountIds' => $this->post('currencyAccountIds'),
        ];

        $annotation = [
            'type'  => '类别',
            'code'  => '科目编码',
            'name'  => '科目名称',
            'pid'   => '上级科目',
            'state' => '科目状态',
        ];
        $rules      = [
            'type'  => 'required',
            'code'  => 'required|numeric',
            'name'  => 'required',
            'pid'   => 'required',
            'state' => 'required',
        ];
        // 校验是否符合规则
        $vt     = new \verify();
        $result = $vt->setAliases($annotation)->validate($field, $rules)->isOk();
        if ($result === false) {
            $json['warn'] = $vt->getErrs()[0];  // 多个规则提示最前面一条
            goto resp;
        }
        $getCodeLength = $this->getCodeLength();
        //判断
        if (!$this->power(self::page, "edit")) {
            $json['warn'] = "你没有编辑" . self::title . "的权限";
        } elseif (static::total(array('table' => self::table, 'where' => "coid = '" . self::$coid . "' and code = '$field[code]' and id !='$id'"))) {
            $json['warn'] = '已存在此编码的科目';
        } elseif (static::total(array('table' => self::table, 'where' => "coid = '" . self::$coid . "' and name = '$field[name]' and pid = '$field[pid]' and id !='$id'"))) {
            $json['warn'] = '已存在此名称的科目';
        } elseif (mb_strlen($field['code']) != $getCodeLength[0]) {
            $json['warn'] = '您填写的编码不符合编码设置中的一级科目编码长度';
        } elseif ($field['assistAccount'] == '是' && count(explode(',', $field['assistAccountIds'])) > 5) {
            $json['warn'] = '最多设置5个辅助核算';
        } elseif ($field['assistAccount'] == '是' && str_contains($field['assistAccountIds'], '客户') && str_contains($field['assistAccountIds'], '供应商')) {
            $json['warn'] = '客户和供应商不可同时存在';
        } elseif ($field['assistAccount'] == '是' && empty($field['assistAccountIds'])) {
            $json['warn'] = '请选择辅助核算';
        } else {
            $temp         = query(self::table, "coid = '" . self::$coid . "' order by list desc");
            $list         = $temp['list'] ? ($temp['list'] + 1) : 1;
            $selfIndex    = $temp['list'] ? ($temp['list'] + 1) : 1;
            $level        = 1;
            $field        = array_merge($field, [
                'id'        => $id,
                'coid'      => self::$coid,
                'list'      => $list,
                'selfIndex' => $selfIndex,
                'level'     => $level,
                'pinyin'    => PYClass::encode($field['name'])
            ]);
            $json['warn'] = static::insert(["table" => self::table, "field" => $field]);
            if (in_array($json['warn'], ["新增成功", "更新成功"])) {
                //添加日志
                $type = mb_substr($json['warn'], 0, 2, 'utf-8');
                $text = $this->control['name'] . $type . "了科目【{$field['code']}-{$field['name']}】";
                $this->logText(["type" => self::page, "text" => $text]);
                //返回
                $_SESSION['warn'] = $json['warn'];
                $json['warn']     = 2;
            }
        }
        resp:
        return json_encode($json, 320);
    }

    /**
     * 编辑页
     * @return string
     */
    public function edit(): string
    {
        $id          = $this->post('id') ?: suiji();
        $info        = query(self::table, " id = '" . $id . "' ");
        $isExitChild = false;
        if (static::total(array('table' => self::table, 'where' => "pid = '$info[id]'")) > 0) {
            $isExitChild = true;
        }
        if (empty($info['id']) || $info['pid'] == '0') {
            $pidName = '-';
            $pid     = '0';
        } else {
            $parent  = query(self::table, "id = '$info[pid]'");
            $pidName = $parent['name'];
            $pid     = $info['pid'];
        }
        if (!empty($this->post('pid'))) {
            //新建下级
            $parent  = query(self::table, "id = '" . $this->post('pid') . "'");
            $pidName = $parent['name'];
            $pid     = $this->post('pid');
        }
        //币别
        $currencyOption = [];
        $all            = find(array('table' => 'currency', 'where' => "coid='" . self::$coid . "' order by time asc"));
        foreach ($all['array'] as $array) {
            $currencyOption[$array['id']] = $array['name'];
        }
        $class   = [
            $info['numAccount'] == '是' ? '' : 'hide',
            $info['assistAccount'] == '是' ? '' : 'hide',
            $info['currencyAccount'] == '是' ? '' : 'hide',
        ];
        $checked = [
            $info['numAccount'] == '是' ? 'checked' : '',
            $info['assistAccount'] == '是' ? 'checked' : '',
            $info['currencyAccount'] == '是' ? 'checked' : '',
        ];
        array_pop(self::$assitOption);
        if ($info['subjectSign'] == '现金流' || (isset($parent['subjectSign']) && $parent['subjectSign'] == '现金流')) {
            //非现金科目去除现金流辅助选项
            self::$assitOption = array_merge(self::$assitOption, ['现金流']);
        }
        $direction = '借';
        if (isset($parent['direction'])) {
            $direction = $parent['direction'];
        }
        if ($info['direction']) {
            $direction = $info['direction'];
        }
        $readOnly = '';
        if ($info['id'] && !$info['isDel']) {
            $readOnly = 'readOnly';
        }
        $disabled = '';
        $tip      = '';
        if (self::total(['table' => 'voucher_detail', 'where' => "coid = '" . self::$coid . "' and subjectId!='' and subjectId = '$info[id]'"]) > 0
            || self::total(['table' => 'business_voucher_template_detail', 'where' => "coid = '" . self::$coid . "' and subjectId!='' and subjectId = '$info[id]'"]) > 0) {
            $disabled = " disabled";
            $tip      = componentClass::tipComponent("科目已被使用，个别信息不支持修改");
        }
        $subMethod = "subForm('subjectEditForm','" . root . "control/adIndex.html?cla=subject&fun=editEdit')";

        $currencyOption = [];
        $currencyAll    = find(['table' => 'currency', 'where' => "coid = '" . self::$coid . "' order by time"]);
        foreach ($currencyAll['array'] as $array) {
            $currencyOption[$array['id']] = $array['code'] . '(' . $array['name'] . ')';
        }

        $html = $this->layerEdit([
            "table"  => [
                [
                    must . '提示：' => "1、如果父级科目已被使用，则自动新增同名的子级科目替换<br>2、如果科目已被使用，个别信息将不支持修改"
                ],
                [
                    must . "科目编码：" => text(["name" => "code", 'other' => $readOnly, "value" => $info['code'] ?: $this->subjectCode($this->post('type'), $pid)]),
                ],
                [
                    must . "科目名称：" => text(["name" => "name", 'other' => $readOnly, "value" => $info['name']]),
                ],
                [
                    must . "上级科目：" => $pidName . hidden(array('name' => 'pid', 'value' => $pid)),
                ],
                [
                    must . "类别：" => $info['type'] ?: $this->post('type'),
                ],
                [
                    must . '余额方向：' => radio(array('name' => 'direction', 'other' => $disabled, 'value' => ['借', '贷'], 'checked' => $direction)) . $tip
                ],
                [
                    must . '科目状态：' => radio(array('name' => 'state', 'value' => ['启用', '停用'], 'checked' => $info['state'] ?: '启用'))
                ],
                [
                    '外币核算：' => select(array('name' => 'currencyAccountIds', 'option' => $currencyOption, 'title' => '请选择外币符号', 'value' => $info['currencyAccountIds']))
                ],
                [
                    "<label class='checkbox'><input name='numAccount' $checked[0] onclick=\"chooseBox(this,'numAccount')\" type='checkbox' value='是'><span></span>&nbsp;数量核算：</label>" => "<span id='numAccount' class='{$class[0]}'>计量单位&nbsp;" . text(array('name' => 'numAccountText', 'class' => 'width100', 'value' => $info['numAccountText'])) . "</span>"
                ],
                [
                    "<label class='checkbox'><input $disabled name='assistAccount' $checked[1] onclick=\"chooseBox(this,'assistAccount')\" type='checkbox' value='是'><span></span>&nbsp;辅助核算：</label>" => "<span id='assistAccount' class='{$class[1]}'>" . checkbox(array('name' => 'assistAccountIds', 'other' => $disabled, 'value' => self::$assitOption, 'checked' => explode(',', $info['assistAccountIds']))) . "</span>" . $tip
                ],
            ],
            'hidden' => hidden(array('name' => 'type', 'value' => $info['type'] ?: $this->post('type'))) . $this->js(),//$voucherMx['id'] ? "<input type='button' class='button' style='background-color: #dadada' disabled value='已使用'>" :
        ]);//

        //返回
        return $this->layer(array(
            "title"  => "编辑",
            "height" => 600,
            "width"  => 800,
            "html"   => $html,
            'button' => $isExitChild ? "<input type='button' class='button' style='background-color: #dadada' disabled value='已使用'>" : "<input onclick=\"$subMethod\" type='button' class='button' value='确认提交'>"
        ));
    }

    /**
     *
     * @return string
     */
    private function js()
    {
        return <<<eof
<script>
function chooseBox(e,id){
    if ($(e).is(":checked")){
          $("#"+id).show();
       }else{
          $("#"+id).hide();
       }
}
</script>
eof;
    }


    public function editEdit()
    {
        $id    = $this->post('id') ?: self::getId();
        $field = [
            'type'               => $this->post('type'),
            'code'               => $this->post('code'),
            'name'               => $this->post('name'),
            'direction'          => $this->post('direction'),
            'pid'                => $this->post('pid'),
            'state'              => $this->post('state'),
            'numAccount'         => $this->post('numAccount') ?: '否',
            'assistAccount'      => $this->post('assistAccount') ?: '否',
            'currencyAccount'    => $this->post('currencyAccountIds') ? '是' : '否',
            'numAccountText'     => $this->post('numAccount') == '是' ? $this->post('numAccountText') : '',
            'assistAccountIds'   => $this->post('assistAccount') == '是' ? implode(',', $this->post('assistAccountIds') ?: []) : '',
            'currencyAccountIds' => $this->post('currencyAccountIds'),
        ];
        if (self::total(['table' => 'voucher_detail', 'where' => "coid = '" . self::$coid . "' and subjectId!='' and subjectId = '$id'"]) > 0
            || self::total(['table' => 'business_voucher_template_detail', 'where' => "coid = '" . self::$coid . "' and subjectId!='' and subjectId = '$id'"]) > 0) {
            unset($field['assistAccount']);
            unset($field['assistAccountIds']);
            unset($field['direction']);
        }
        $annotation = [
            'type'  => '类别',
            'code'  => '科目编码',
            'name'  => '科目名称',
            'pid'   => '上级科目',
            'state' => '科目状态',
        ];
        $rules      = [
            'type'  => 'required',
            'code'  => 'required|numeric',
            'name'  => 'required',
            'pid'   => 'required',
            'state' => 'required',
        ];
        // 校验是否符合规则
        $vt     = new \verify();
        $result = $vt->setAliases($annotation)->validate($field, $rules)->isOk();
        if ($result === false) {
            $json['warn'] = $vt->getErrs()[0];  // 多个规则提示最前面一条
            goto resp;
        }
        $where         = " id = '$id' ";
        $info          = query(self::table, $where);
        $parent        = query(self::table, "id = '$field[pid]'");
        $level         = $parent['id'] ? $parent['level'] + 1 : 1;
        $getCodeLength = $this->getCodeLength();
        $length        = 0;
        for ($i = 0; $i < $level; $i++) {
            $length += $getCodeLength[$i] ?? 0;
        }
        //判断
        if (!$this->power(self::page, "edit")) {
            $json['warn'] = "你没有编辑" . self::title . "的权限";
        } elseif (static::total(array('table' => self::table, 'where' => "coid = '" . self::$coid . "' and code = '$field[code]' and id !='$id'"))) {
            $json['warn'] = '已存在此编码的科目';
        } elseif (static::total(array('table' => self::table, 'where' => "coid = '" . self::$coid . "' and name = '$field[name]' and pid = '$field[pid]' and id !='$id'"))) {
            $json['warn'] = '已存在此名称的科目';
        } elseif ($level > $this->level) {
            $json['warn'] = '最多新建' . $this->level . '层科目';
        } elseif ($getCodeLength[$level] && mb_strlen($field['code']) != $length) {
            $json['warn'] = '科目编码不符合编码设置中的编码长度';
        } elseif (isset($field['assistAccount']) && $field['assistAccount'] == '是' && empty($field['assistAccountIds'])) {
            $json['warn'] = '请选择辅助核算';
        } elseif (isset($field['assistAccount']) && $field['assistAccount'] == '是' && count(explode(',', $field['assistAccountIds'])) > 5) {
            $json['warn'] = '最多设置5个辅助核算';
        } elseif (isset($field['assistAccount']) && $field['assistAccount'] == '是' && str_contains($field['assistAccountIds'], '客户') && str_contains($field['assistAccountIds'], '供应商')) {
            $json['warn'] = '客户和供应商不可同时存在';
        } else {
            if ($parent['subjectSign'] == '现金流') {
                $field['subjectSign'] = '现金流';
            }

            if ($field['pid'] == '0') {
                $temp      = query(self::table, "coid = '" . self::$coid . "' order by list desc");
                $list      = $temp['list'] ? ($temp['list'] + 1) : 1;
                $selfIndex = $temp['list'] ? ($temp['list'] + 1) : 1;

            } else {
                $list      = $parent['list'];
                $temp      = query(self::table, "coid = '" . self::$coid . "' and level = '$level' order by list desc");
                $selfIndex = $temp['selfIndex'] ? ($temp['selfIndex'] + 1) : 1;
            }
            if (!$info['id']) {
                $field        = array_merge($field, [
                    'id'        => $id,
                    'coid'      => self::$coid,
                    'list'      => $list,
                    'selfIndex' => $selfIndex,
                    'level'     => $level,
                    'pinyin'    => PYClass::encode($field['name'])
                ]);
                $json['warn'] = static::insert(["table" => self::table, "field" => $field]);


            } else {
                $json['warn'] = static::update([
                    "table" => self::table,
                    "field" => $field,
                    "where" => $where
                ], false);
            }

            if (in_array($json['warn'], ["新增成功", "更新成功"])) {

                if (!$info['id'] && (static::total(array('table' => 'voucher_detail', 'where' => "subjectId = '$field[pid]'")) > 0 ||
                        static::total(array('table' => 'business_voucher_template_detail', 'where' => "subjectId = '$field[pid]'")) > 0 ||
                        static::total(array('table' => 'business_voucher_subject', 'where' => "subjectId = '$field[pid]'")) > 0 ||
                        static::total(array('table' => 'material', 'where' => "subjectId = '$field[pid]'")) > 0
                    )) {
                    //如果父级有凭证，则新增一级相同名称的子级科目
                    $code  = $this->subjectCode($parent['type'], $parent['id']);
                    $suiji = suiji();
                    static::insert(array(
                        'table' => self::table,
                        'field' => [
                            'id'                 => $suiji,
                            'coid'               => self::$coid,
                            'list'               => $list,
                            'selfIndex'          => $selfIndex + 1,
                            'level'              => $level,
                            'type'               => $parent['type'],
                            'code'               => $code,
                            'name'               => $parent['name'],
                            'pinyin'             => $parent['pinyin'],
                            'direction'          => $parent['direction'],
                            'pid'                => $parent['id'],
                            'initMoney'          => $parent['initMoney'],
                            'borrowMoney'        => $parent['borrowMoney'],
                            'loanMoney'          => $parent['loanMoney'],
                            'subjectSign'        => $parent['subjectSign'],
                            'state'              => $parent['state'],
                            'numAccount'         => $parent['numAccount'],
                            'assistAccount'      => $parent['assistAccount'],
                            'currencyAccount'    => $parent['currencyAccount'],
                            'numAccountText'     => $parent['numAccountText'],
                            'assistAccountIds'   => $parent['assistAccountIds'],
                            'currencyAccountIds' => $parent['currencyAccountIds'],
                        ]
                    ));
                    //凭证替换父级科目
                    $this->replaceSubjectId($parent['id'], $suiji, $code);
                }
                //添加日志
                $type = mb_substr($json['warn'], 0, 2, 'utf-8');
                $text = $this->control['name'] . $type . "了" . self::title . " id：【" . $id . '】';
                $this->logText(["type" => self::page, "text" => $text]);
                //返回
                $_SESSION['warn'] = $json['warn'];
                $json['warn']     = 2;
            }
        }
        resp:
        return json_encode($json, 320);
    }

    // 操作中转
    public function operate()
    {
        $act  = $this->post('act') ?? '';
        $pwd  = false; // 需要密码
        $form = $power = '';
        switch ($act) {
            default:
                $act      = 'del';
                $msg      = '删除' . self::title;
                $title    = self::page . 'Delete';
                $function = 'delete';
                $form     = self::page . 'OperateForm, listForm,lossForm,costForm,interestsForm,debtForm';
                $power    = '';
                break;
        }
        if (!$this->power(self::page, $act)) {
            $_SESSION['warn'] = '你还没有' . $msg . '的权限';
            $json             = [
                'warn' => 2,
                'href' => root . 'control/adIndex.html?cla=' . $this->get('cla') . '&fun=home',
            ];
        } else {
            return $this->confirm([
                'title'    => $title,
                'function' => $function,
                'form'     => $form,
                'power'    => $power,
                'pwd'      => $pwd,
            ]);
        }

        resp:
        return json_encode($json, 320);
    }


    /**
     * 导出
     */
    public function exportData()
    {

        if (!$this->power(self::page, 'export')) {
            $_SESSION['warn'] = '你还没有导出的权限';
        } else {
            $tr     = [];
            $title  = ["科目编码", "科目名称", '类别', '余额方向(借/贷)', '数量核算', '辅助核算', '外币核算'];
            $result = find(array('table' => self::table, 'where' => "coid = '" . self::$coid . "' and level = 1 order by code asc"));
            if (is_array($result)) {
                foreach ($result['array'] as $array) {
                    $res = $this->loopSubjectExport($array);
                    $tr  = array_merge($tr, $res);
                }
            }
            $text = $this->control['name'] . "导出了" . self::title;
            $this->logText(["type" => self::page, "text" => $text]);
            $this->excelOut($title, $tr, self::title . ".xlsx");
        }
        header("Location:" . getenv("HTTP_REFERER"));
        exit(0);
    }


    private function loopSubjectExport($array): array
    {
        $tr          = [];
        $isExitChild = false;
        if (static::total(array('table' => self::table, 'where' => "pid = '$array[id]'")) > 0) {
            $isExitChild = true;
        }
        $empty = '';
        if ($array['level'] > 1) {
            for ($i = 1; $i < $array['level']; $i++) {
                $empty .= " ";
            }
        }
        $currency = query('currency', "id = '$array[currencyAccountIds]'");
        $temp     = array($empty . $array['code'], $empty . $array['name'], $array['type'], $array['direction'], $array['numAccountText'], $array['assistAccountIds'], $currency['code']);
        $tr[]     = $temp;
        //判断是否有下级分类
        if ($isExitChild) {
            $levelTwoRes = find(array('table' => self::table, 'where' => "pid = '$array[id]' order by code"));
            foreach ($levelTwoRes['array'] as $val) {
                $res = $this->loopSubjectExport($val);
                $tr  = array_merge($tr, $res);
            }
        }
        return $tr;
    }

    /**
     * 下载模板
     */
    public function downloadModel()
    {
        $templateId     = $this->get('templateId');
        if (!$this->power(self::page, 'import')) {
            $_SESSION['warn'] = '你还没有导入的权限';
        } else {
            $exampleData[] = ['1001', '库存现金', '资产类', '借', '件', '客户,供应商', 'USD,GBP'];
            $excel         = $this->excelHead();
            $fileName      = self::title . '导入模板-' . importTemplateClass::getName($templateId) . '.xlsx';
            $filePath      = $excel->fileName($fileName, 'sheet1');
            $format        = new \Vtiful\Kernel\Format($filePath->getHandle());
            $templateField = importTemplateClass::templateField(self::page, 'importFieldInit', id:$templateId);
            $index         = 0;
            foreach ($templateField as $k => $array) {
                if ($array['display']) {
                    $backgroundStyle = null;
                    if (importTemplateClass::getIsMustValue($this->importFieldInit(), $array['columnName'])) {
                        //必填项判断
                        $backgroundStyle = $format->background(
                            0xFFC04B
                        )->toResource();
                    }
                    $filePath->insertText(0, $index, $array['aliasName'], '', $backgroundStyle);
                    foreach ($exampleData as $y => $example) {
                        $exampleVal = match ($array['columnName']) {
                            '科目编码' => $example[0],
                            '科目名称' => $example[1],
                            '类别' => $example[2],
                            '余额方向' => $example[3],
                            '数量核算' => $example[4],
                            '辅助核算' => $example[5],
                            '外币核算' => $example[6],
                            default => '',
                        };
                        $filePath->insertText($y + 1, $index, $exampleVal);
                    }
                    $index++;
                }
            }
            $text = $this->control['name'] . "下载了科目导入模板";
            $this->logText(["type" => self::page, "text" => $text]);
            $this->excelOutPut($filePath, $fileName);
            exit(0);
        }
        header("Location:" . getenv("HTTP_REFERER"));
    }

    /*数据导入分析*/
    public function importData()
    {
        $templateId     = $this->post('templateId');
        if (!$this->power(self::page, 'import')) {
            $json['warn'] = '你还没有导入的权限';
        } else {
            $fomatArray = [];//导入数据格式同一为TYPE_STRING
            foreach ($this->importFieldInit() as $value) {
                $fomatArray[] = \Vtiful\Kernel\Excel::TYPE_STRING;
            }
            $data      = $this->importHead(format: $fomatArray);
            $x         = 0;
            $text      = '';
            $headArray = [];
            $row_list  = 0;
            foreach ($data as $i => $row) {
                $row_list++;
                if ($i == 0) {
                    $templateField = importTemplateClass::templateField(self::page, 'importFieldInit', id:$templateId);
                    $headArray = importTemplateClass::combinHead($templateField,$row);
                }
                if ($i > 0) {
                    $rowData = formSubArray($row);
                    //只接收模板中选中的字段的值
                    $cell = [];
                    foreach ($headArray as $index => $headName) {
                        $cell[$headName] = $rowData[$index] ?? '';
                    }
                    //初始化未被模板需要的字段的值
                    foreach ($this->importFieldInit() as $value) {
                        $cell[$value['columnName']] = $cell[$value['columnName']] ?? '';
                    }
                    $currency = query('currency', "code = '$cell[外币核算]' and coid = '" . self::$coid . "'");
                    if (empty($currency['id'])) {
                        $text .= "第【{$row_list}】行：未找到外币【{$cell['外币核算']}】<br>";
                        continue;
                    }
                    $field = [
                        'type'               => $cell['类别'],
                        'code'               => $cell['科目编码'],
                        'name'               => $cell['科目名称'],
                        'pinyin'             => PYClass::encode($cell['科目名称']),
                        'direction'          => $cell['余额方向'],
                        'numAccount'         => $cell['数量核算'] ? '是' : '否',
                        'assistAccount'      => $cell['辅助核算'] ? '是' : '否',
                        'currencyAccount'    => $currency['id'] ? '是' : '否',
                        'numAccountText'     => $cell['数量核算'],
                        'assistAccountIds'   => $cell['辅助核算'],
                        'currencyAccountIds' => $currency['id'],
                    ];

                    $annotation = [
                        'type'      => '类别',
                        'code'      => '科目编码',
                        'name'      => '科目名称',
                        'direction' => '余额方向',
                    ];
                    $rules      = [
                        'type'      => 'required',
                        'code'      => 'required',
                        'name'      => 'required',
                        'direction' => 'required',
                    ];
                    $subject    = query(self::table, "code = '$field[code]' and coid = '" . self::$coid . "'");
                    // 校验是否符合规则
                    $vt     = new \verify();
                    $result = $vt->setAliases($annotation)->validate($field, $rules)->isOk();
                    if ($result === false) {
                        $text .= "第【{$row_list}】行：" . $vt->getErrs()[0] . "<br>";  // 多个规则提示最前面一条
                    } else {
                        self::$codeRule = $this->getCodeLength();
                        $length         = strlen($field['code']);//科目编码长度
                        $codeNum        = 0;
                        $pid            = false;//父级科目ID
                        foreach (self::$codeRule as $index => $val) {
                            $codeNum += $val;
                            if ($length == $codeNum) {
                                //当前科目层级
                                if ($index > 0) {
                                    $pidCode = mb_substr($field['code'], 0, $codeNum - $val, 'utf8');//父级科目编码
                                    $temp    = query(self::table, "coid = '" . self::$coid . "' and code = '$pidCode'");
                                    if (empty($temp['id'])) {
                                        $text .= "第【{$row_list}】行导入失败：未找到父级科目<br>";
                                        break;
                                    } else {
                                        $pid = $temp['id'];
                                    }
                                } else {
                                    $pid = '0';
                                }
                                break;
                            }
                        }
                        if ($pid === false) {
                            continue;
                        }
                        if ($pid == '0') {
                            $temp      = query(self::table, "coid = '" . self::$coid . "' order by list desc");
                            $list      = $temp['list'] ? ($temp['list'] + 1) : 1;
                            $selfIndex = $temp['list'] ? ($temp['list'] + 1) : 1;
                            $level     = 1;
                        } else {
                            $parent = query(self::table, "id = '$pid'");
                            $list   = $parent['list'];
                            $level  = $parent['level'] + 1;
                            if ($level > $this->level) {
                                $text .= "第【{$row_list}】行导入失败：最多新建{$this->level}层层级<br>";
                                continue;
                            }
                            $temp      = query(self::table, "coid = '" . self::$coid . "' and level = '$level' order by list desc");
                            $selfIndex = $temp['selfIndex'] ? ($temp['selfIndex'] + 1) : 1;
                        }
                        $field['pid'] = $pid;
                        if (empty($subject['id'])) {
                            $field = array_merge($field, [
                                'id'        => suiji(),
                                'coid'      => self::$coid,
                                'list'      => $list,
                                'selfIndex' => $selfIndex,
                                'level'     => $level
                            ]);
                            $warn  = static::insert(["table" => self::table, "field" => $field]);
                        } else {
                            if (self::total(['table' => 'voucher_detail', 'where' => "coid = '" . self::$coid . "' and subjectId!='' and subjectId = '$subject[id]'"]) > 0
                                || self::total(['table' => 'business_voucher_template_detail', 'where' => "coid = '" . self::$coid . "' and subjectId!='' and subjectId = '$subject[id]'"]) > 0) {
                                unset($field['assistAccount']);
                                unset($field['assistAccountIds']);
                                unset($field['direction']);
                            }
                            $warn = static::update([
                                "table" => self::table,
                                "field" => $field,
                                "where" => "id = '$subject[id]'"
                            ]);
                        }
                        if (in_array($warn, ["新增成功", "更新成功"])) {
                            $x++;
                            if (!$subject['id'] && $field['pid'] != '0' &&
                                (static::total(array('table' => 'voucher_detail', 'where' => "subjectId = '$field[pid]'")) > 0 ||
                                    static::total(array('table' => 'business_voucher_template_detail', 'where' => "subjectId = '$field[pid]'")) > 0 ||
                                    static::total(array('table' => 'business_voucher_subject', 'where' => "subjectId = '$field[pid]'")) > 0 ||
                                    static::total(array('table' => 'material', 'where' => "subjectId = '$field[pid]'")) > 0)
                            ) {
                                //如果父级有凭证，则新增一级相同名称的子级科目
                                $parent = query(self::table, "id = '$pid'");
                                if ($parent['id']) {
                                    $code  = $this->subjectCode($parent['type'], $parent['id']);
                                    $suiji = suiji();
                                    static::insert(array(
                                        'table' => self::table,
                                        'field' => [
                                            'id'                 => $suiji,
                                            'coid'               => self::$coid,
                                            'list'               => $list,
                                            'selfIndex'          => $selfIndex + 1,
                                            'level'              => $level,
                                            'type'               => $parent['type'],
                                            'code'               => $code,
                                            'name'               => $parent['name'],
                                            'pinyin'             => $parent['pinyin'],
                                            'direction'          => $parent['direction'],
                                            'pid'                => $parent['id'],
                                            'initMoney'          => $parent['initMoney'],
                                            'borrowMoney'        => $parent['borrowMoney'],
                                            'loanMoney'          => $parent['loanMoney'],
                                            'subjectSign'        => $parent['subjectSign'],
                                            'state'              => $parent['state'],
                                            'numAccount'         => $parent['numAccount'],
                                            'assistAccount'      => $parent['assistAccount'],
                                            'currencyAccount'    => $parent['currencyAccount'],
                                            'numAccountText'     => $parent['numAccountText'],
                                            'assistAccountIds'   => $parent['assistAccountIds'],
                                            'currencyAccountIds' => $parent['currencyAccountIds'],
                                        ]
                                    ));
                                    //凭证替换父级科目
                                    $this->replaceSubjectId($parent['id'], $suiji, $code);
                                }
                            }
                            $text .= "第【{$row_list}】行导入成功<br>";
                        } else {
                            $text .= "第【{$row_list}】行导入失败：编辑失败<br>";
                        }
                    }
                }
            }
            $total        = count($data) - 1;
            $json['data'] = [
                'text'  => $text,
                'title' => "您导入了{$total}条数据，成功{$x}条，失败" . ($total - $x) . "条",
            ];
            $text         = $this->control['name'] . '导入了文件：' . $_FILES['file']['name'] . '：' . $text;
            $this->logText(["type" => self::page, "text" => $text]);
            $json['warn'] = 2;
        }
        return json_encode($json, 320);
    }

    /**
     * 删除
     * @return bool|string
     */
    public function delete()
    {
        $array = $this->post('listId') ?? $this->post('id');
        if (!$this->power(self::page, "del")) {
            $json['warn'] = "你没有删除的权限";
        } elseif (empty($array)) {
            $json['warn'] = "你一个数据都没有选择呢";
        } else {
            $text  = "";
            $x     = 0;
            $array = is_array($array) ? $array : [$array];
            foreach ($array as $id) {
                $info = query(self::table, " id = '$id' ");
                if ($info['state'] != '停用') {
                    $warn = "删除失败：不是停用状态";
                } elseif (!$info['isDel']) {
                    $warn = "删除失败：初始科目不可删除";
                } elseif (static::total(array('table' => 'voucher_detail', 'where' => "subjectId = '$id'")) > 0) {
                    $warn = "删除失败：已被使用";
                } else {
                    //最后删除基本参数
                    delete(array("table" => self::table, "where" => " id = '$id' "));
                    delete(array("table" => 'subject_assist', "where" => " orderId = '$id' "));
                    //子凭证删除后由父级凭证代替
                    $parent = query('subject', "id = '$info[pid]'");
                    $this->replaceSubjectId($id, $info['pid'], $parent['code']);
                    //返回
                    $warn = "删除成功";
                    $x++;
                }
                $text .= "科目【{$info['name']}】,编码【" . $info['code'] . "】" . $warn . "。<br>";
            }
            //添加日志
            $text = $this->control['name'] . "删除了" . self::title . "，结果如下：<br>" . $text;
            $this->logText(array("type" => self::page, "text" => $text));
            $_SESSION['warn'] = "删除了" . $x . "个" . self::title . "，详情见系统日志。";
            $json['warn']     = 2;
            $json['href']     = root . "control/adIndex.html?cla=" . $this->get('cla') . "&fun=home";
        }
        return json_encode($json, 320);
    }


    public function replaceSubjectId($pid, $subjectId, $subjectCode)
    {
        //凭证替换父级科目
        update(array(
            'table' => 'voucher_detail',
            'field' => [
                'subjectId'   => $subjectId,
                'subjectCode' => $subjectCode,
            ],
            'where' => "subjectId = '$subjectId'"
        ));
        //业务凭证
        update(array(
            'table' => 'business_voucher_template_detail',
            'field' => [
                'subjectId' => $subjectId,
            ],
            'where' => "subjectId = '$pid'"
        ));
        //业务凭证
        update(array(
            'table' => 'business_voucher_subject',
            'field' => [
                'subjectId'   => $subjectId,
                'subjectCode' => $subjectCode,
            ],
            'where' => "subjectId = '$pid'"
        ));
        //资产负债表
//                                    update(array(
//                                        'table' => 'asset_debt_formula',
//                                        'field' => [
//                                            'subjectId' => $subjectId,
//                                        ],
//                                        'where' => "subjectId = '$pid'"
//                                    ));
//                                    //利润表
//                                    update(array(
//                                        'table' => 'profit_income_formula',
//                                        'field' => [
//                                            'subjectId' => $subjectId,
//                                        ],
//                                        'where' => "subjectId = '$pid'"
//                                    ));
//                                    //凭证模板配置
//                                    update(array(
//                                        'table' => 'period_end_setting_detail',
//                                        'field' => [
//                                            'subjectId' => $subjectId,
//                                        ],
//                                        'where' => "subjectId = '$pid'"
//                                    ));
        //期初
        update(array(
            'table' => 'subject_assist',
            'field' => [
                'orderId' => $subjectId,
            ],
            'where' => "orderId = '$pid'"
        ));
        //银行账户绑定科目
        update(array(
            'table' => 'account',
            'field' => [
                'subjectId' => $subjectId,
            ],
            'where' => "subjectId = '$pid'"
        ));
        //物料档案绑定科目
        update(array(
            'table' => 'material',
            'field' => [
                'subjectId' => $subjectId,
            ],
            'where' => "subjectId = '$pid'"
        ));
        update(array(
            'table' => 'material',
            'field' => [
                'costSubjectId' => $subjectId,
            ],
            'where' => "costSubjectId = '$pid'"
        ));
        update(array(
            'table' => 'material',
            'field' => [
                'incomeSubjectId' => $subjectId,
            ],
            'where' => "incomeSubjectId = '$pid'"
        ));
    }

    /**
     * 获取带父级名称的科目名称
     * @param $id
     * @return mixed
     */
    public static function getName($id): mixed
    {
        $subject = query(self::table, "id = '$id'");
        if (empty($subject['id'])) {
            return '';
        }
        if ($subject['pid'] != '0') {
            return self::getName($subject['pid']) . '-' . $subject['name'];
        } else {
            return $subject['name'];
        }
    }

    /**
     * 获取科目名称
     * @param $id
     * @param string $sign
     * @return mixed
     */
    public static function getShortName($id, $sign = 'all')
    {
        $subject = query(self::table, "id = '$id'");
        return match ($sign) {
            'name' => $subject['name'],
            'code' => $subject['code'],
            default => $subject['code'] . $subject['name'],
        };
    }

    /**
     * 获取一段会计科目的ID
     * @param $fromSubjectId
     * @param $toSubjectId
     * @return array
     */
    public function getFromToSubject($fromSubjectId, $toSubjectId): array
    {
        $multObj = new multiColumnAccountClass();
        $columns = [];
        $multObj->loopSubjectIds($fromSubjectId, $columns);
        if (!empty($toSubjectId)) {
            $formSubject = query(self::table, "id = '$fromSubjectId'");
            $toSubject   = query(self::table, "id = '$toSubjectId'");
            $all         = find(array('table' => 'subject', "where" => "coid = '" . self::$coid . "' and code > '$formSubject[code]' and code <= '$toSubject[code]' order by code asc"));
            foreach ($all['array'] as $array) {
                $columns[] = $array['id'];
            }

        }
        return $columns;
    }


    /**
     * 切换是否显示停用科目
     * @return bool|string
     */
    public function showStopSubjectEdit(): bool|string
    {
        $company                      = query('company', "coid = '" . self::$coid . "'");
        $setting                      = $company['setting'] ? json_decode($company['setting'], true) : [];
        $setting['isShowStopSubject'] = $setting['isShowStopSubject'] ?? 1;
        if ($setting['isShowStopSubject'] == 1) {
            $setting['isShowStopSubject'] = 2;
        } else {
            $setting['isShowStopSubject'] = 1;
        }
        $warn = self::update(['table' => 'company', 'field' => ['setting' => json_encode($setting, 320)], 'where' => "coid = '$company[coid]'"]);
        if ($warn == '更新成功') {
            $json['warn'] = 2;
        } else {
            $json['warn'] = $warn;
        }
        return json_encode($json, 320);
    }

    /**
     * 导入模板字段初始化
     * @return array[]
     */
    public function importFieldInit($classify = ''): array
    {
        return match ($classify) {
            default => [
                [
                    'columnName' => '科目编码',
                    'aliasName'  => '科目编码',
                    'isMust'     => true,
                ],
                [
                    'columnName' => '科目名称',
                    'aliasName'  => '科目名称',
                    'isMust'     => true,
                ],
                [
                    'columnName' => '类别',
                    'aliasName'  => '类别',
                    'isMust'     => true,
                ],
                [
                    'columnName' => '余额方向',
                    'aliasName'  => '余额方向(借/贷)',
                    'isMust'     => true,
                ],
                [
                    'columnName' => '数量核算',
                    'aliasName'  => '数量核算',
                    'isMust'     => false,
                ],
                [
                    'columnName' => '辅助核算',
                    'aliasName'  => '辅助核算',
                    'isMust'     => false,
                ],
                [
                    'columnName' => '外币核算',
                    'aliasName'  => '外币核算',
                    'isMust'     => false,
                ],
            ]
        };
    }
}
